package cn.samir.sudoku.core;

import java.util.ArrayList;

import android.content.Context;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AbsListView.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.PopupWindow;
import android.widget.TextView;
import cn.samir.sudoku.R;
import cn.samir.sudoku.util.LogUtils;
import cn.samir.sudoku.util.Utils;

public class InputPopupWindow implements OnClickListener, OnItemClickListener {
	private static final String TAG = "InputPopupWindow";
	private static final int SHOW = 1;
	private static final int DISMISS = 2;
	private static final int INPUT_MARK = 1;
	private static final int INPUT_NORMAL = 2;
	private static final int INPUT_HELP = 3;
	GridView gridView;
	TextView tv_preStep;
	TextView tv_reback;
	TextView tv_clear;
	TextView tv_mark;
	View parentView;
	boolean isShowing = false;
	int inputMode = INPUT_NORMAL;
	// int[] ints = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	Context mContext;
	MyAdapter mAdapter;
	ArrayList<InputItem> mInputItems = new ArrayList<InputItem>();
	InputNumberListener inputNumberListener;
	View mPopView;
	WindowManager mWindowManager;
	PopupViewContainer mContentView;
	PopupWindow m;
	SubItemView mSubItemView;
	WindowManager.LayoutParams params;
	Number99View number99View;
	MoveAction moveAction = new MoveAction();
	Handler handler = new Handler() {
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case SHOW:
				break;
			case DISMISS:
				break;
			default:
				break;
			}
		};
	};

	public InputPopupWindow(Context context, View parentView) {

		this.mContext = context;
		this.parentView = parentView;
		mContentView = new PopupViewContainer(context);
		// popupViewContainer = new PopupViewContainer(mContext);
		mPopView = View.inflate(context, R.layout.inputpopupwindow, null);
		mContentView.addView(mPopView);
		mWindowManager = (WindowManager) context
				.getSystemService(Context.WINDOW_SERVICE);
		initSettings();
		initViews(mContentView);
		// mContentView.setBackgroundDrawable(new BitmapDrawable());
		params = new WindowManager.LayoutParams();
		// toast 直接取消
		params.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
		params.height = WindowManager.LayoutParams.WRAP_CONTENT;
		params.width = WindowManager.LayoutParams.MATCH_PARENT;
		// 让该view后面的view可以接到触摸事件
		params.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
				| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
		params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
				| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
		params.gravity = Gravity.BOTTOM;
		params.token = parentView.getWindowToken();
	}

	private void initSettings() {
		for (int i = 0; i < 10; i++) {
			mInputItems.add(new InputItem((i + 1) + "", (i + 1), 0));
			Log.i(TAG, "put a item in list");
		}
	}

	private void initViews(View view) {
		gridView = Utils.getView(view, R.id.gv_number);
		mAdapter = new MyAdapter(mInputItems, mContext);
		gridView.setAdapter(mAdapter);
		gridView.setOnItemClickListener(this);
		tv_clear = Utils.getView(view, R.id.tv_clear);
		tv_reback = Utils.getView(view, R.id.tv_reback);
		//tv_reback.setVisibility(View.GONE);
		tv_preStep = Utils.getView(view, R.id.tv_preStep);
		//tv_preStep.setVisibility(View.GONE);
		tv_mark = Utils.getView(view, R.id.tv_mark);
		tv_clear.setOnClickListener(this);
		tv_mark.setOnClickListener(this);
		tv_preStep.setOnClickListener(this);
		tv_reback.setOnClickListener(this);
	}

	public Number99View getNumber99View() {
		return number99View;
	}

	public void setNumber99View(Number99View number99View) {
		this.number99View = number99View;
	}

	class MyAdapter extends BaseAdapter {
		Context context;
		ArrayList<InputItem> inputItems = null;

		public MyAdapter(ArrayList<InputItem> inputItems, Context context) {
			super();
			this.context = context;
			this.inputItems = new ArrayList<InputItem>();
			this.inputItems.addAll(inputItems);

		}

		@Override
		public int getCount() {
			int count = 0;
			if (inputItems != null) {
				count = inputItems.size();
			}
			return count;
		}

		public ArrayList<InputItem> getInputItems() {
			return inputItems;
		}

		public void clearAndAddAll(ArrayList<InputItem> items) {
			if (inputItems != null) {
				inputItems.clear();
				inputItems.addAll(items);
				LogUtils.i(TAG, "item_size=" + items.size() + "");
				update();
			}
		}

		public void update() {
			notifyDataSetChanged();
		}

		@Override
		public Object getItem(int position) {
			return inputItems.get(position);
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			InputItemView view;
			if (convertView == null) {
				view = new InputItemView(context);
			} else {
				view = (InputItemView) convertView;
			}
			// TextView tv = (TextView) view.findViewById(R.id.tv_number);
			// ImageView iv = (ImageView) view.findViewById(R.id.iv_status);
			int parentWidth = parent.getWidth();
			int childWidth = parentWidth / 5;
			int childHeight = (int) (childWidth * 0.618);
			LayoutParams layoutParams = new LayoutParams(childWidth,
					childHeight);
			view.setLayoutParams(layoutParams);

			InputItem inputItem = inputItems.get(position);
			LogUtils.i(TAG, "p=" + position + "," + inputItem.toString());
			if (!Utils.isNumberLegal(position + 1)) {
				inputItem.text = "H";
			}
			view.setmInputItem(inputItem);
			return view;
		}
	}

	public void showInputWindow(SubItemView subItemView) {
		this.mSubItemView = subItemView;
		show();
	}

	@Override
	public void onClick(View v) {
		if (inputNumberListener == null) {
			return;
		}
		switch (v.getId()) {
		case R.id.tv_clear:
			moveAction.action = MoveAction.INPUT_CLEAR;
			inputMode = INPUT_NORMAL;
			break;
		case R.id.tv_mark:
			// 标记不需要发送指令，改变键盘现实
			moveAction.action = MoveAction.INPUT_MARK;
			if (INPUT_MARK != inputMode) {
				inputMode = INPUT_MARK;
			} else {
				inputMode = INPUT_NORMAL;
			}
			changeToMarkStatus(inputMode);
			break;
		case R.id.tv_preStep:
			inputMode = INPUT_NORMAL;
			moveAction.action = MoveAction.INPUT_PRE_STEP;
			break;
		case R.id.tv_reback:
			inputMode = INPUT_NORMAL;
			moveAction.action = MoveAction.INPUT_REBACK;
			break;
		}
		inputNumberListener.postAction(moveAction);
	}

	private void changeToMarkStatus(int mode) {

		ArrayList<InputItem> items = mInputItems;// 获取所有的输入按键
		// SubItemView subItemView =
		// GlobalStatus.getSudokuSubItem();//获取当前被按下的方框

		int count = 0;
		if (items != null) {
			count = items.size();// 10
		}
		for (int i = 0; i < count; i++) {
			int status = items.get(i).status;// 状态
			if (mode == INPUT_MARK) {
				if (mSubItemView.isHasMarks(i + 1)) {// 当前项是否含有这个标记
					status = 2;// 0不显示，1显示，2 灰色
				} else if (status == 1) {
					status = 0;
				} else if (status == 0) {
					status = 1;
				}
				items.get(i).status = status;
			} else {
				items.get(i).status = 0;
			}
			LogUtils.i(TAG, "i=" + i + "status=" + status);
		}
		mAdapter.clearAndAddAll(items);
		// mAdapter.notifyDataSetChanged();
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		if (inputNumberListener == null) {
			return;
		}
		InputItem inputItem = (InputItem) mAdapter.getItem(position);
		MoveAction moveAction = new MoveAction();
		if (position == (mInputItems.size() - 1)) {// 这个不需要发送到外部
			moveAction.action = MoveAction.INPUT_HELP;
			if (Utils.getConfig(mContext, "isHelpButtonEnabled") == Utils.ENABLE) {
				helpme();
			} else {
				LogUtils.showShortToast(mContext, "可以在设置界面开启提示信息");
			}
		} else {
			if (inputMode == INPUT_MARK) {
				moveAction.action = MoveAction.INPUT_MARK;
				// moveAction.value = inputItem.number;
			} else if (inputMode == INPUT_NORMAL || inputMode == INPUT_HELP) {
				moveAction.action = MoveAction.INPUT_NUMBER;

			}
			moveAction.value = inputItem.number;
			inputNumberListener.postAction(moveAction);
		}

		// dismiss();
	}

	public void helpme() {
		if (inputMode == INPUT_HELP) {
			ArrayList<InputItem> items = mInputItems;// 获取所有的输入按键
			// SubItemView subItemView =
			// GlobalStatus.getSudokuSubItem();//获取当前被按下的方框

			int count = 0;
			if (items != null) {
				count = items.size();// 10
			}
			for (int i = 0; i < count; i++) {
				InputItem item = items.get(i);
				item.status = 0;// 0不显示，1显示，2 灰色
			}

			mAdapter.clearAndAddAll(items);
			inputMode = INPUT_NORMAL;

		} else {
			int[] numbers = new int[10];
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++) {
					SubItemView subItemView = (SubItemView) number99View
							.getChildAt(i * 9 + j);
					if ((subItemView.getmValue() != 0)
							&& (mSubItemView.mSudokuSubItem.xPoint == subItemView.mSudokuSubItem.xPoint
									|| mSubItemView.mSudokuSubItem.yPoint == subItemView.mSudokuSubItem.yPoint || mSubItemView.mSudokuSubItem.groupNum == subItemView.mSudokuSubItem.groupNum)) {
						numbers[subItemView.getmValue()] = subItemView
								.getmValue();
						LogUtils.i(TAG, subItemView.getmValue() + "不能填写");
					}
				}
			}
			ArrayList<InputItem> items = mInputItems;// 获取所有的输入按键
			// SubItemView subItemView =
			// GlobalStatus.getSudokuSubItem();//获取当前被按下的方框

			int count = 0;// 10
			if (items != null) {
				count = items.size();// 10
			}
			for (int i = 1; i < count; i++) {
				InputItem item = items.get(i - 1);
				if (numbers[i] == 0) {// 0不显示，1显示，2 灰色
					item.status = 1;
				} else {
					item.status = 2;
				}
			}
			mAdapter.clearAndAddAll(items);
			inputMode = INPUT_HELP;
		}
	}

	public InputNumberListener getInputNumberListener() {
		return inputNumberListener;
	}

	public void setInputNumberListener(InputNumberListener inputNumberListener) {
		this.inputNumberListener = inputNumberListener;
	}

	public void dismiss() {
		if (isShowing) {
			isShowing = false;
			mWindowManager.removeViewImmediate(mContentView);
		}
	}

	public void show() {
		if (!isShowing) {
			isShowing = true;
			for (int i = 0; i < mInputItems.size(); i++) {
				mInputItems.get(i).status = 0;
			}
			inputMode = INPUT_NORMAL;
			mAdapter.clearAndAddAll(mInputItems);
			mWindowManager.addView(mContentView, params);
		}
	}

	public boolean isShowing() {
		return isShowing;
	}

	private class PopupViewContainer extends FrameLayout {
		public static final String TAG = "PopupWindow.PopupViewContainer";

		public PopupViewContainer(Context context) {
			super(context);
		}

		@Override
		public boolean dispatchKeyEvent(KeyEvent event) {
			if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
				if (getKeyDispatcherState() == null) {
					return super.dispatchKeyEvent(event);
				}

				if (event.getAction() == KeyEvent.ACTION_DOWN
						&& event.getRepeatCount() == 0) {
					KeyEvent.DispatcherState state = getKeyDispatcherState();
					if (state != null) {
						state.startTracking(event, this);
					}
					return true;
				} else if (event.getAction() == KeyEvent.ACTION_UP) {
					KeyEvent.DispatcherState state = getKeyDispatcherState();
					if (state != null && state.isTracking(event)
							&& !event.isCanceled()) {
						dismiss();
						return true;
					}
				}
				return super.dispatchKeyEvent(event);
			} else {
				return super.dispatchKeyEvent(event);
			}
		}

		@Override
		public boolean dispatchTouchEvent(MotionEvent ev) {
			return super.dispatchTouchEvent(ev);
		}

		@Override
		public boolean onTouchEvent(MotionEvent event) {
			final int x = (int) event.getX();
			final int y = (int) event.getY();

			if ((event.getAction() == MotionEvent.ACTION_DOWN)
					&& ((x < 0) || (x >= getWidth()) || (y < 0) || (y >= getHeight()))) {
				dismiss();
				return true;
			} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
				dismiss();
				return true;
			} else {
				return super.onTouchEvent(event);
			}
		}

	}

}
